package com.ccp.dev.workflow.controller;

import com.alibaba.fastjson.JSON;
import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.annotion.ActionExecOrder;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.RequestUtil;
import com.ccp.dev.core.util.StringPool;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.form.model.FormField;
import com.ccp.dev.form.service.FormDefService;
import com.ccp.dev.form.service.FormFieldService;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysOrgService;
import com.ccp.dev.workflow.model.*;
import com.ccp.dev.workflow.service.ActDefModelService;
import com.ccp.dev.workflow.service.AgentSettingService;
import com.ccp.dev.workflow.service.BpmDefVarService;
import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.util.JSONUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * ClassDescribe 流程代理设定 控制器类
 * @author :fanruiqi
 * Date: 2019-09-20
 * Since:1
 * To change this template use File | Settings | File Templates.
 */
@Controller
@RequestMapping(UrlConstants.PROJECT_ROOT+ UrlConstants.PROJECT_MODULE_WORKFLOW+"/agentSetting")
public class AgentSettingController extends SysBaseController {
    private static final Logger logger = LoggerFactory.getLogger(AgentSettingService.class);

    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private AgentSettingService agentSettingService;
    @Resource
    private FormDefService formDefService;
    @Resource
    private FormFieldService formFieldService;
    @Resource
    private BpmDefVarService bpmDefVarService;
    @Resource
    private ActDefModelService actDefModelService;


    /**
     * 个人办公，设置中心，流程代理授权
     * @return 跳转页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/authList")
    @Action(description = "流程代理授权页面",ownermodel = SysAuditModelType.PROCESS_CENTER,exectype = "页面跳转日志")
    public String viewAuthList (Model model){
        model.addAttribute("isManage",0);
        return "workflow/agentSetting/manageList";
    }

    /**
     * 流程管理，流程管理，代理配置管理
     * @return 跳转页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/manageList")
    @Action(description = "代理配置管理页面",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,exectype = "页面跳转日志")
    public String viewManageList (Model model){
        model.addAttribute("isManage",1);
        return getAutoView();
    }

    /**
     * 编辑代理设定，List页面编辑按钮入口(个人入口)  从manageList进
     * @return 跳转页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/edit")
    @Action(description = "编辑代理设定-List页面编辑按钮个人入口",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,exectype = "页面跳转日志")
    public String viewEdit (HttpServletRequest request, Model model){
        String id = RequestUtil.getString(request,"id");
        this.getToStartView(id,model);
        // agentType=0 为个人入口，agentType=1为管理入口
        model.addAttribute("agentType", StringPool.ZERO);
        return getAutoView();
    }

    /**
     * 编辑代理设定，edit页面编辑条件入口(管理入口) 从authList进
     * @return 跳转页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/editAll")
    @Action(description = "编辑代理设定-edit页面编辑按钮管理入口",ownermodel = SysAuditModelType.PROCESS_CENTER,exectype = "页面跳转日志")
    public String viewEditAll(HttpServletRequest request, Model model){
        String id = RequestUtil.getString(request,"id");
        this.getToStartView(id,model);
        // agentType=0 为个人入口，agentType=1为管理入口
        model.addAttribute("agentType",StringPool.ONE);
        //跳转路径为edit页面
        return "workflow/agentSetting/edit";
    }

    /**
     * 编辑代理设定，edit页面设置代理条件入口(个人入口)
     * @return 跳转页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+"/editCondition")
    @Action(description = "编辑代理设定-edit页面设置代理条件入口",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,exectype = "页面跳转日志")
    public String viewEditCondition (HttpServletRequest request, Model model){
        String flowKey=RequestUtil.getString(request, "flowKey");
        String id=RequestUtil.getString(request, "id");

        ActDefModel actDefModel = actDefModelService.getMainByDefKey(flowKey);
        String modelId = actDefModel.getId();
        List<FormField> flowVars = formFieldService.queryFlowVarByFlowProcDefIdOrParentProcDefId(modelId,null,true);
        String tableId = formDefService.getTableIdByModelId(actDefModel.getProcDefId());
        //获取自定义变量
        List<BpmDefVar> bpmDefVars = bpmDefVarService.queryByModelId(modelId);
        model.addAttribute("id",id)
                .addAttribute("tableId", tableId)
                .addAttribute("flowVars", flowVars)
                .addAttribute("bpmDefVars", bpmDefVars)
                .addAttribute("modelId",actDefModel.getId());
        return getAutoView();
    }

    /**
     * 获取部分代理的流程名称列表
     * 仅当授权类型为^部分代理^时启用^流程名称^点击事件
     * @return 返回数据
     */
    @RequestMapping("/queryAgentDefModelList")
    @Action(description = "获取部分代理的流程名称列表",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,detail = "获取部分代理的流程名称列表")
    @ResponseBody
    public ResultData viewAgentDefModelList (HttpServletRequest request){
        String id = RequestUtil.getString(request,"id");
        List<AgentDefModel> modelList = agentSettingService.queryBySettingId(id);
        return getResultDataSuccess("query.success",modelList);
    }

    /**
     * 获取流程代理授权页面列表数据
     * @param request
     * @return 返回结果
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_LIST)
    @Action(description = "流程代理授权页面列表数据查询",ownermodel = SysAuditModelType.PROCESS_CENTER,detail = "流程代理授权页面列表数据查询成功")
    @ResponseBody
    public ResultData list(HttpServletRequest request){
        return this.queryList(request,false);
    }

    /**
     * 获取代理配置管理页面列表数据
     * @param request
     * @return 返回结果
     */
    @RequestMapping("/manageList")
    @Action(description = "代理配置管理页面列表数据查询",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,detail = "代理配置管理页面列表数据查询成功")
    @ResponseBody
    public ResultData manageList(HttpServletRequest request){
        return this.queryList(request,true);
    }

    /**
     * 代理设定删除
     * @param request
     * @return 返回结果
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_DELETE)
    @Action(description = "删除代理设定",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,execOrder = ActionExecOrder.BEFORE,detail = "流程代理设定删除<#if success>成功<#else>失败</#if>")
    @ResponseBody
    public ResultData del(HttpServletRequest request){
        try {
            String[] ids = RequestUtil.getStringAryByStr(request,"ids");
            agentSettingService.delByIdArray(ids);
            SysAuditThreadLocalHolder.putParamerter("success",true);
            return getResultDataSuccess("delete.success");
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
            SysAuditThreadLocalHolder.putParamerter("success",false);
            return getResultDataError("delete.failure");
        }
    }

    /**
     * 更新流程代理状态
     * @param request
     * @return 返回结果
     */
    @RequestMapping("/updStatus")
    @Action(description = "流程代理状态更新",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,detail = "流程代理状态更新为<#if success>启动<#else>禁用</#if>")
    @ResponseBody
    public ResultData updStatus(HttpServletRequest request){
        //流程代理ID
        String id = RequestUtil.getString(request,"id");
        //流程代理状态，启用为1，禁用为0
        short status=RequestUtil.getShort(request,"status",(short)-1);
        //是否有效传值
        if(StringUtil.isEmpty(id)){
            return getResultDataError("agentSetting.import.id.failure");
        }else if(status==-1){
            return getResultDataError("agentSetting.import.invalid.failure");
        }
        try {
            //先取出来再存进去
            AgentSetting agentSetting = agentSettingService.getOneById(id);
            agentSetting.setEnabled(status);
            agentSettingService.update(agentSetting);
            if(AgentSetting.ENABLED_NO.equals(status)){
                SysAuditThreadLocalHolder.putParamerter("success",false);
                return getResultDataSuccess("agentSetting.disable.success");
            }else {
                SysAuditThreadLocalHolder.putParamerter("success",true);
                return getResultDataSuccess("agentSetting.startUp.success");
            }
        }catch (Exception e){
            logger.error(e.getMessage());
            e.printStackTrace();
            return getResultDataError("operation.failure");
        }
    }

    /**
     * 保存代理
     * @param request
     * @return
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_SAVE)
    @Action(description = "流程代理设置保存",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT,detail = "流程代理设置<#if success>保存<#else>更新</#if>成功")
    @ResponseBody
    public ResultData save(HttpServletRequest request){
        String  orgId      = ContextUtil.getCurrentOrgId();
        String  tenId      = sysOrgService.getTenIdByOrgId(orgId);
        AgentSetting setting   = this.getFormObject(request);
        if(setting==null){
            return getResultDataError("agentSetting.invalid.failure");
        }
        try {
            if(StringUtil.isEmpty(setting.getId())){
                setting.setId(UUIDUtils.getUUIDFor32());
                setting.setTenantId(tenId);
                setting.setCreateTime(new Date());
                agentSettingService.addAll(setting);
                SysAuditThreadLocalHolder.putParamerter("success",true);
                return getResultDataSuccess("agentSetting.add.success");
            }else{
                setting.setTenantId(tenId);
                agentSettingService.updateAll(setting);
                SysAuditThreadLocalHolder.putParamerter("success",false);
                return getResultDataSuccess("agentSetting.update.success");
            }
        }catch (Exception e){
            logger.error(e.getMessage());
            e.printStackTrace();
            return getResultDataError("save.failure");
        }
    }

    /**
     * 验证流程是否可以代理
     * @param request
     * @return 返回结果
     * @throws Exception
     */
    @RequestMapping("/validateCanAgentByFlow")
    @Action(description = "验证流程是否可以代理",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
    @ResponseBody
    public ResultData  validateCanAgentByFlow(HttpServletRequest request) throws  Exception{

        String curUserId = ContextUtil.getCurrentUserId();
        String [] flowKeys = RequestUtil.getStringAryByStr(request, "flowKeys");
        List<String> flowKeyList = new ArrayList<String>(Arrays.asList(flowKeys));
        Date startTime = RequestUtil.getDate(request, "startTime");
        Date endTime = RequestUtil.getDate(request, "endTime");
        String id = RequestUtil.getString(request, "agentSettingId", null);
        for(String flowKey:flowKeyList){
            boolean flag = agentSettingService.isConflictAgainstPartialOrConditionByFlow(flowKey,startTime,endTime,curUserId,id);
            if(flag){
                return getResultDataError("agentSetting.validate.setting.failure");
            }
        }
        return getResultDataSuccess("agentSetting.validate.success");
    }

    /**
     * 验证是否与存在的其它代理冲突
      * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/validateConflictAgainstAll")
    @Action(description = "验证是否与存在的其它代理冲突",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
    @ResponseBody
    public ResultData validateConflictAgainstAll(HttpServletRequest request)throws Exception{
        boolean flag = this.isConflictAgainstGeneral(request,false);
        if(flag){
            return getResultDataError("agentSetting.validate.all.failure");
        }
        return getResultDataSuccess("agentSetting.validate.success");
    }

    /**
     * 验证是否与存在的有效全权代理代理冲突
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/validateConflictAgainstGeneral")
    @Action(description = "验证是否与存在的有效全权代理代理冲突",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
    @ResponseBody
    public ResultData validateConflictAgainstGeneral(HttpServletRequest request)throws Exception{
        boolean flag = this.isConflictAgainstGeneral(request,true);
        if(flag){
            return getResultDataError("agentSetting.validate.general.failure");
        }
        return getResultDataSuccess("agentSetting.validate.success");
    }

    /**
     * 提取公共方法，获取List列表数据
     * @param request
     * @param isManage
     * @return
     */
    private ResultData queryList(HttpServletRequest request,boolean isManage){
        QueryFilter filter = new QueryFilter(request);
        //获取当前用户组织id，并根据组织id查找租户id，根据租户id查找代理配置数据
        String  orgId      = ContextUtil.getCurrentOrgId();
        String  tenId      = sysOrgService.getTenIdByOrgId(orgId);
        //list方法与manageList方法的区别
        if(!isManage) {
            //获取当前用户ID
            String curUserId   = ContextUtil.getCurrentUserId();
            filter.addFilter("authId", curUserId);
        }
        filter.addFilter("tenantId", tenId);
        List<AgentSetting> list=agentSettingService.queryList(filter);
        //补充AgentCondition
        for(AgentSetting agentSetting:list){
            if(agentSetting.getAuthType()==AgentSetting.AUTHTYPE_CONDITION){
                List<AgentCondition> agentConditionList =  this.getAgentCondition(agentSetting.getId(),agentSetting);
                agentSetting.setAgentConditionList(agentConditionList);
            }
        }
        return getResultDataSuccess("query.success", filter.getPageBean().getTotalCount(),list);
    }

    /**
     * 提取公共方法，验证代理冲突
     * @param request
     * @param isGeneral 是否是全局代理验证
     * @return
     * @throws Exception
     */
    private boolean isConflictAgainstGeneral(HttpServletRequest request, boolean isGeneral) throws Exception{
        String curUserId = ContextUtil.getCurrentUserId();
        Date startTime = RequestUtil.getDate(request, "startTime");
        Date endTime = RequestUtil.getDate(request, "endTime");
        String id = RequestUtil.getString(request, "agentSettingId", null);
        return agentSettingService.isConflictAgainstGeneral(startTime, endTime, curUserId,id,isGeneral);
    }

    /**
     * 提取公共方法，取得AgentSetting 实体
     * @param request
     * @return
     * @throws Exception
     */
    private AgentSetting getFormObject(HttpServletRequest request) {
        JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] { "yyyy-MM-dd" }));

        String json=RequestUtil.getString(request, "json");
        json = StringEscapeUtils.unescapeHtml4(json);
        int agentType=RequestUtil.getInt(request, "agentType",0);
        AgentSetting agentSetting  = JSON.parseObject(json, AgentSetting.class);
        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        //为普通入口的 授权 （0 授权人为自己）  否则为管理入口（1 授权人为页面所选择的人员）
        if(agentType!=1){
            agentSetting.setAuthId(sysUser.getUserId());
            agentSetting.setAuthName(sysUser.getFullName());
        }
        if(AgentSetting.AUTHTYPE_GENERAL ==agentSetting.getAuthType()){
            agentSetting.getAgentDefList().clear();
            agentSetting.getAgentConditionList().clear();
            agentSetting.setFlowKey(null);
            agentSetting.setFlowName(null);
        }else if(AgentSetting.AUTHTYPE_PARTIAL ==agentSetting.getAuthType()){
            agentSetting.getAgentConditionList().clear();
            agentSetting.setFlowKey(null);
            agentSetting.setFlowName(null);
        }else if(AgentSetting.AUTHTYPE_CONDITION ==agentSetting.getAuthType()){
            agentSetting.getAgentDefList().clear();
            agentSetting.setAgentId(null);
            agentSetting.setAgent(null);
        }else{
//          无效代理设定
            return null;
        }

        return agentSetting;
    }

    /**
     * 提取公共方法，获取编辑页面相关数据
     * @param id
     * @param model
     * @return
     */
    private Model getToStartView(String id,Model model) {
        AgentSetting agentSetting=agentSettingService.getOneById(id);
        if(agentSetting!=null){
            if(agentSetting.getAuthType()==AgentSetting.AUTHTYPE_CONDITION){
                List<AgentCondition> agentConditionList =  this.getAgentCondition(id,agentSetting);
                agentSetting.setAgentConditionList(agentConditionList);
            }else{
                List<AgentDefModel> agentDefList=agentSettingService.queryAgentDefModelById(id);
                agentSetting.setAgentDefList(agentDefList);
            }
        }
        model.addAttribute("agentSetting",agentSetting);
        return model;
    }

    /**
     * 当代理授权类型为“条件授权”时，用于回显规则agentCondition
     * @param id
     * @return 返回数据
     */
    @RequestMapping("/getAgentCondition")
    @Action(description = "条件授权回显规则agentCondition",ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
    @ResponseBody
    public ResultData getAgentCondition(String id){
        AgentSetting agentSetting=agentSettingService.getOneById(id);
        if(agentSetting!=null){
           List<AgentCondition> agentConditionList =  this.getAgentCondition(id,agentSetting);
           return getResultDataSuccess("query.success",agentConditionList);
        }
        return getResultDataError("query.failure");
    }

    /**
     * 提取公共方法，获取agentCondition
     * @param id
     * @param agentSetting
     * @return 返回数据
     */
    private List<AgentCondition> getAgentCondition(String id, AgentSetting agentSetting) {
        List<AgentCondition> agentConditionList=agentSettingService.queryAgentConditionList(id);
        if(BeanUtils.isNotEmpty(agentConditionList)){
            AgentCondition condition = agentConditionList.get(0);
            String condJsonStr = condition.getCondition();
            com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(condJsonStr);
            String tableId = jsonObject.getString("tableId");

            ActDefModel actDefModel = actDefModelService.getMainByDefKey(agentSetting.getFlowKey());
            if(BeanUtils.isNotEmpty(actDefModel)){
                String currentTableId = formDefService.getTableIdByModelId(actDefModel.getProcDefId());
                if( StringUtil.isEmpty(currentTableId) || ( StringUtil.isNotEmpty(currentTableId) && !currentTableId.equals(tableId))){
                    agentConditionList.clear();
                }
            }
        }
        return agentConditionList;
    }
}
